﻿using FastCode.Architecture;
using FastCode.DTO;
using FastCode.Helper;
using FastCode.Models;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SqlSugar;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

//using IOFile = System.IO;
using IOFile = System.IO.File;
namespace FastCode.Controllers
{
    public class GenerageCodeController : ApiPureController
    {

        DBConfigService dBConfigService;
        public GenerageCodeController(ISqlSugarClient db, DBConfigService dBConfigService) : base(db)
        {
            this.dBConfigService = dBConfigService;
        }

        /// <summary>
        /// 生成后端api和前端页面
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<object> GeApiAndFront(DBConfigDTO dto)
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            var projectPath = Directory.GetParent(currentDirectory)?.Parent;
            var frontViewsPath = projectPath?.FullName + "\\FrontEnd\\src\\views";
            var controllerPath = $"{currentDirectory}/Controllers/{dto.TableName}Controller.cs";
            var servicePath = $"{currentDirectory}/Services/{dto.TableName}Service.cs";
            var vuePath = $"{frontViewsPath}/{dto.TableName}.vue";
            if (!dto.IsForce && (System.IO.File.Exists(controllerPath) || System.IO.File.Exists(servicePath) || System.IO.File.Exists(vuePath)))
            {
                return Msg.Success(new {
                    isExist = true
                }, $"{dto.TableName} 已经生成过，是否覆盖？");
            }

            //改为从类文件生成
            //Assembly.GetExecutingAssembly().
            var curAssembly = Assembly.GetAssembly(typeof(BaseModel));
            if (curAssembly == null)
            {
                return Msg.Error("找不到对应程序集");
            }


            var curModel = curAssembly
               .GetTypes() // 获取程序集中所有类型
               .FirstOrDefault(t => t.Name == dto.TableName);

            if (curModel == null)
            {
                return Msg.Error("找不到实体类:" + dto.TableName);
            }

            //string currentDirectory = Directory.GetCurrentDirectory();

            //var projectPath = Directory.GetParent(currentDirectory)?.Parent;
            //var frontViewsPath = projectPath?.FullName + "\\FrontEnd\\src\\views";
            var srcPath = projectPath?.FullName + "\\FrontEnd\\src\\";

            var tableNameLower = dto.TableName?.FirstCharToLower();
            #region controller
            var templateContent = await IOFile.ReadAllTextAsync(currentDirectory + "/T4Template/FastCodeController.txt");
            templateContent = templateContent.Replace("{TableName}", dto.TableName);
            templateContent = templateContent.Replace("{TableNameLower}", tableNameLower);
            await IOFile.WriteAllTextAsync($"{currentDirectory}/Controllers/{dto.TableName}Controller.cs", templateContent);
            #endregion

            #region service
            var serviceContent = await IOFile.ReadAllTextAsync(currentDirectory + "/T4Template/FService.txt");
            serviceContent = serviceContent.Replace("{TableName}", dto.TableName);
            await IOFile.WriteAllTextAsync($"{currentDirectory}/Services/{dto.TableName}Service.cs", serviceContent);
            #endregion

            var vueContent = await IOFile.ReadAllTextAsync($"{frontViewsPath}/CURDTemplate.vue");

            vueContent = vueContent.Replace("CURDTemplate", dto.TableName);

            //查询条件
            var searchConditionList = new List<SearchCondition>();

            //curModel
            var propInfos = curModel.GetProperties();
            var ignoreFields = new HashSet<string>() { "Id", "CreateTime", "UpdateTime", "IsDeleted" };
            var columnNames = new List<ColumnConfig>();
            foreach (var propInfo in propInfos)
            {
                if (ignoreFields.Contains(propInfo.Name))
                {
                    continue;
                }
                var addItem = new SearchCondition()
                {
                    //FieldName = propInfo.Name,
                    Label = propInfo.Name,
                    //CSharpTypeName = propInfo.PropertyType.Name,
                };
                addItem.ConditionalModels = new List<ConditionalModel>();
                var conditionalModel = new ConditionalModel()
                {
                    FieldName = propInfo.Name,
                    CSharpTypeName = propInfo.PropertyType.Name
                };

                addItem.ConditionalModels.Add(conditionalModel);

                //有UIType 特性
                var uiType = propInfo.GetCustomAttribute<UITypeAttribute>();
                if (uiType != null)
                {
                    if (uiType.ColumnConfig.Label.IsHasValue())
                    {
                        addItem.Label = uiType.ColumnConfig.Label;
                    }
                    addItem.ControlType = uiType.ColumnConfig.ControlType;
                }


                GenerageCodeHelper.SetColumnConfig(propInfo, columnNames);

                switch (propInfo.PropertyType)
                {
                    //日期类型，生成start，end 时间
                    case Type t when t == typeof(DateTime):
                        // Do something for DateTime
                        addItem.ControlType = EUIType.Date;
                        conditionalModel.FieldName = propInfo.Name + ConstData.SplitStart;
                        conditionalModel.ConditionalType = ConditionalType.GreaterThanOrEqual;
                        //addItem.FieldName = propInfo.Name + "Start";
                        var item2 = JsonConvert.DeserializeObject<ConditionalModel>(JsonConvert.SerializeObject(conditionalModel));
                        item2.FieldName = propInfo.Name + ConstData.SplitEnd;
                        item2.ConditionalType = ConditionalType.LessThanOrEqual;

                        addItem.ConditionalModels.Add(item2);
                        //searchConditionList.Add(item2);
                        break;

                    case Type t when t == typeof(string):
                        conditionalModel.ConditionalType = ConditionalType.Like;
                        //addItem.ConditionalType = ConditionalType.Like;
                        addItem.ControlType = EUIType.Text;
                        break;

                    default:
                        //addItem.ConditionalType = ConditionalType.Equal;
                        conditionalModel.ConditionalType = ConditionalType.Equal;
                        break;
                }

                searchConditionList.Add(addItem);
            }



            var queryJson = JsonConvert.SerializeObject(searchConditionList);
            //vueContent = vueContent.Replace("SearchConditions: [],", $"SearchConditions:{queryJson}");
            //SearchConditions:.*\[(.|\s\n)+\]
            vueContent = Regex.Replace(vueContent, @"SearchConditions:.*\[(.|\s\n)+\}\],", $"SearchConditions:{queryJson}");

            //set var bgcolumnNames = []
            var columnJson = JsonConvert.SerializeObject(columnNames);
            vueContent = Regex.Replace(vueContent, @"var bgcolumnNames.*?\]", $"var bgcolumnNames={columnJson}");
            //写入前端
            await IOFile.WriteAllTextAsync($"{frontViewsPath}/{dto.TableName}.vue", vueContent);

            //配置路由
            var newRoute = new RouteConfig()
            {
                Path = $"/{dto.TableName?.ToLower()}",
                Label = dto.TableName,
                Component = $"/src/views/{dto.TableName}.vue",
            };

            //路由是否已存在
            if (!db.Queryable<RouteConfig>().Any(x => !x.IsDeleted && x.Path == newRoute.Path))
            {
                await db.Insertable(newRoute).ExecuteCommandAsync();
            }

            return Msg.Success(null, "ok");
        }

    }
}
